#include "pipeline.h"

#include <cctype>
#include <string>
#include <string_view>

namespace cfg
{

// 作用：normalize_keys transformer，支持 style=lowercase/snake_case。
// 说明：将对象键统一规范化，便于上层使用一致的键风格访问。
class TransformerNormalizeKeys : public ITransformer
{
public:
    bool transform(Builder & builder,
                   const PluginOptions & options,
                   std::vector<ConfigError> & out_errors) override
    {
        std::string style;
        if (auto it = options.find("style"); it != options.end())
            style = it->second;

        auto to_lower = [](std::string_view s)
        {
            std::string r;
            r.reserve(s.size());
            for (unsigned char c : s)
                r.push_back(static_cast<char>(std::tolower(c)));
            return r;
        };

        auto to_snake = [&](std::string_view s)
        {
            std::string r;
            r.reserve(s.size() * 2);
            bool prev_underscore = false;
            auto is_alpha = [](unsigned char ch) { return std::isalpha(ch); };

            for (size_t i = 0; i < s.size(); ++i)
            {
                unsigned char c = static_cast<unsigned char>(s[i]);
                if (std::isalnum(c))
                {
                    if (std::isupper(c))
                    {
                        // 计算当前大写连续段的起止，用于处理尾部缩写（如 ID/CPU 等）的合并规则
                        size_t start = i;
                        while (start > 0 && std::isupper(static_cast<unsigned char>(s[start - 1])))
                            --start;
                        size_t j = i;
                        while (j < s.size() && std::isupper(static_cast<unsigned char>(s[j])))
                            ++j;
                        bool run_terminal =
                            (j >= s.size()) || !is_alpha(static_cast<unsigned char>(s[j]));
                        bool is_first_in_run = (i == start);

                        // 插入下划线规则：
                        //  - 大写段首字母且前面已有输出时，总是插入一个下划线；
                        //  - 段内的其余大写字母：
                        //      * 若该大写连续段在字符串末尾或后接非字母（缩写），则不在段内部再插入下划线（userID -> user_id）。
                        //      * 否则在段内继续插入下划线（HTTPServer -> h_t_t_p_server）。
                        if (!r.empty() && !prev_underscore)
                        {
                            if (is_first_in_run)
                            {
                                r.push_back('_');
                            }
                            else if (!run_terminal)
                            {
                                r.push_back('_');
                            }
                        }

                        r.push_back(static_cast<char>(std::tolower(c)));
                        prev_underscore = false;
                    }
                    else
                    {
                        // 小写字母或数字：直接追加
                        r.push_back(static_cast<char>(std::tolower(c)));
                        prev_underscore = false;
                    }
                }
                else
                {
                    // 非字母数字：将其作为分隔符，避免重复下划线
                    if (!prev_underscore && !r.empty())
                    {
                        r.push_back('_');
                        prev_underscore = true;
                    }
                }
            }
            return r;
        };

        if (style.empty())
        {
            // 默认 lowercase
            builder.normalize_keys([&](std::string_view k) { return to_lower(k); });
        }
        else if (style == "snake_case")
        {
            builder.normalize_keys([&](std::string_view k) { return to_snake(k); });
        }
        else if (style == "lowercase")
        {
            builder.normalize_keys([&](std::string_view k) { return to_lower(k); });
        }
        else
        {
            // 非法取值：记录一条诊断并回退到 lowercase
            ConfigError e{
                Errc::Other, std::string("normalize_keys: invalid style '") + style + "'", {}};
            e.notes = "fallback to lowercase";
            out_errors.emplace_back(std::move(e));
            builder.normalize_keys([&](std::string_view k) { return to_lower(k); });
        }
        return true;
    }
};

// 静态注册内置 transformer
REGISTER_TRANSFORMER("normalize_keys", TransformerNormalizeKeys);

} // namespace cfg
